package com.fusingdata.UtilsQR;

import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import com.fusingdata.bean.KeyBean;
import com.fusingdata.bean.SignatureBean;
import com.fusingdata.bean.UserCert;
import com.fusingdata.exception.QRSDKException;

import org.litepal.crud.DataSupport;

import java.math.BigInteger;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * Created by DawnOct on 2017/9/27.
 */

public class QRutils {
    /**
     * 重新获得公钥key
     *
     * @param certCallBack certCallBack
     * @return key
     */
    public static synchronized void generateKey(GenerateKeyCallBack certCallBack) {
        KeyPair keyPair = RSAUtils.generateRSAKeyPair(RSAUtils.DEFAULT_KEY_SIZE);
        if (keyPair != null) {
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();


            saveKeyToLocal(publicKey, privateKey, certCallBack);
        } else {
            certCallBack.onSaveResult(false, "");
        }

    }

    /**
     * 重新获得公钥key(同步)
     *
     * @return key
     */
    public static synchronized String generateKeySyn() {
        KeyPair keyPair = RSAUtils.generateRSAKeyPair(RSAUtils.DEFAULT_KEY_SIZE);
        if (keyPair != null) {
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

            BigInteger modulus1 = publicKey.getModulus();
            byte[] Nbytes1 = modulus1.toByteArray();
            String N = HexUtils.bytesToHexString(Nbytes1);
            int length = N.length();
            if (length == 194) {
                N = N.substring(2);
            }


            saveKeyToLocal(publicKey, privateKey);
            return N;
        } else {
            return "";
        }

    }
//    //计算用户证书签名和用户元数据合在一起的HASH1值(成功)
//    private static void testHASH1() throws NoSuchAlgorithmException {
//        String content = "268081F2A8451320C31BC0CF8C156A97EFFA8E8E3AA2222E0A4E9FCF358FAC395FA03729704646581895BD07FBE4AB4D0E4F6F7688588944F009D331A2A2A4FBAE88C6034846C8FD3FDD68C7CCBDD026048CC8BDA3A58324A72E3E1CF27B26F7DB2A5A1523A61A3A87ABED0B0FD02CDAF4B3AB368F8F6C46E3CB44609ACF5CAB81FDBE5C0B4EED713365F866D86ECB2EDE03E532E239948493990900000000FFFF000000000000000001017FFFFFFF010203040506070809000102030405060708090001020304050607080900";
//        //常用算法：MD5、SHA、CRC
//        MessageDigest digest = MessageDigest.getInstance("SHA1");
//        byte[] decode = Hex.decode(content);
//        byte[] result = digest.digest(decode);
//        //消息摘要的结果一般都是转换成16 进制字符串形式展示
//        String hex = Hex.encode(result);
//        //MD5 结果为16 字节（128 个比特位）、转换为16 进制表示后长度是32 个字符
//        //SHA 结果为20 字节（160 个比特位）、转换为16 进制表示后长度是40 个字符
//        System.out.println(hex);
//    }
//
//    //使用N E 方式获得私钥 公钥 , 并对得到的96字节HaSH值. 进行加密.
//    private static void testNED() throws Exception {
//        //密钥的n, e值
//        String e = "00010001";
//        String n = "A8DA1916CB48FE8D1C0042A2209186F7AF3DF951A8E99D1595CC075125165825670EAB5113C559616E2ADFC1F53214516E02BABA786B5F57E7777C84AEF9AD7B8615B74C6D81FDBE5C0B4EED713365F866D86ECB2EDE03E532E2399484939909";
//        String d = "029A06AF8559C0F352BD15C9BFF8F76489AE9450D13FEA927E87568DB0BB0F080CD615916C9DAFDE7FE72E4C03A4F3849498BFD61EB2CCE51EC780762B3E239BEF5B8F34B29944484A248E7894E5A86DE4850A121CA0332EAEE3599AFF414711";
//        Long longE = Long.parseLong(e, 16);
////        Long longN = Long.parseLong(n, 16);
////        String str = new BigInteger(n, 16).toString(10);
////        Long longD = Long.parseLong(d, 16);
//        String modulus = new BigInteger(n, 16).toString(10);
//        String publicExponent = longE.toString();
//        PublicKey publicKey1 = RSAUtil.getPublicKey(modulus, publicExponent);
//        String privateExponent = new BigInteger(d, 16).toString(10);
////        PrivateKey privateKey1 = RSAUtil.getPrivateKey(modulus, privateExponent);
//
//        //Hash值和用户元数据填充后的96个字节
//        String data_96 = "4BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB00000000FFFF000000000000000001017FFFFFFF0102030405060708090001020304050607080900010203040506070809003DDF834D9B70137BB6BE5FF5D84AE7880FC6A817BC";
//        //私钥加密后得到的用户签名
//        String aa = "06BE150FF53E7BA8BB0AB2F5C48F4EE1D09022E784642BD65AD47B802C531AA2DDBE1792E9C253EFECA6540CBF0CE840DEAFD84B8F6FD4FE3F7E78D2A876970718E19D38F5D3C8435AAFF978A36AC053E3631294F735464C240A1EAF5A4395AE";
//        byte[] decode = Hex.decode(aa);
//        byte[] bytes = RSAUtil.decryptByPublicKeyForSpilt(decode, publicKey1.getEncoded());
//        String encode = Hex.encode(bytes);
//        //对96个字节加密.  进行私钥加密,得到用户签名
////        byte[] data_96_byte = Hex.decode(data_96);
////        byte[] bytes = RSAUtil.encryptByPrivateKeyForSpilt(data_96_byte, privateKey1.getEncoded());
////        String encode = Hex.encode(bytes);
//    }

    /**
     * 写入用户证书(异步)
     *
     * @param certData 证书相关的字符串
     */
    public static synchronized void writeUserCert(final String certData,
                                                  @Nullable final WriteUsertCertCallBack callBack) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                SignatureBean signatureBean = updateSignature(certData, callBack);
                if (callBack != null) {
                    if (signatureBean != null) {
                        DataSupport.deleteAll(SignatureBean.class);
                        callBack.onResult(signatureBean.save(), 0);
                        //todo 测试使用
//                        DButil01.copyDataBaseToSD(SDKApplication.getContext(), "key", "sdDemo02");
                    }
                }
            }
        }).start();

    }

    /**
     * 写入用户证书(同步)
     *
     * @param certData 证书相关的字符串
     */
    public static synchronized boolean writeUserCertSyn(final String certData) {
        SignatureBean signatureBean = updateSignature(certData);
        if (signatureBean != null) {
            DataSupport.deleteAll(SignatureBean.class);
            return signatureBean.save();
        }
        return false;
    }

    /**
     * 查询用户证书剩余有效时长(异步)
     *
     * @param callBack callBack
     */
    public static void findSignatrueAsyn(final FindUsertCertCallBack callBack) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                List<SignatureBean> all = DataSupport.findAll(SignatureBean.class);
                if (all != null && all.size() > 0) {
                    SignatureBean signatureBean = all.get(0);
                    long l1 = getRemainValidTime(signatureBean);
                    callBack.onSuccess(l1);
                } else {
                    callBack.onFail(-1);
                }
            }
        }).start();

    }


    /**
     * 查询用户证书剩余有效时长(同步)
     *
     * @return 签名证书的剩余有效时长(单位毫秒)
     */
    public static int findSignatrueSyn() {
        List<SignatureBean> all = DataSupport.findAll(SignatureBean.class);
        if (all != null && all.size() > 0) {
            SignatureBean signatureBean = all.get(0);
            long l = getRemainValidTime(signatureBean);
            return (int) (l);//返回剩余有效时长
        }
        return -1;
    }

//    /**
//     * 生成乘车二维码
//     *
//     * @param passengerInfo 乘客信息
//     */
//    public static Bitmap generateQR(String passengerInfo) throws Exception {
//        String localPrivateKey = getLocalPrivateKey();//私钥字符串
//        if (TextUtils.isEmpty(localPrivateKey))
//            throw new QRSDKException("101", "The publicKey cannot be null, need to call generateKey method first");
//        PrivateKey privateKey = RSAUtils.getPrivateKey(localPrivateKey.getBytes());//抛异常
//        byte[] encryptBytes = RSAUtils.encryptByPrivateKeyForSpilt(passengerInfo.getBytes(), privateKey.getEncoded());
//        String encryStr = Base64Decoder01.encode(encryptBytes);//加密后的乘客信息
//        //先要从数据库读取用户签名
//        SignatureBean signatureBean = getSignatrueSyn();
//        if (signatureBean == null)
//            throw new QRSDKException("102", "UserCert cannot be null, need to call writeUserCert method first ");//签名不存在的情况
//        long remainValidTime = getRemainValidTime(signatureBean);
//        if (remainValidTime < 0)
//            throw new QRSDKException("103", "The signature is expired");//签名过期的情况
//        //拼接的字符串(签名文件内容,加密后的乘客信息)
//        //01010101005701020304050607080900000000010000000101020304050607080900FFFFFFFFFFFFFFFF0000000000FFFF000000000000000001017FFFFFFF010203040506070809000102030405060708090001020304050607080900
//        String textContent = signatureBean.getContent();
//        if (TextUtils.isEmpty(textContent))
//            throw new QRSDKException("104", "The two-dimensional code content cannot be empty");
//        return CodeUtils.createImage(textContent, 400, 400, null);
////        return null;
//        //带logo
////        return CodeUtils.createImage(textContent, 400, 400, BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher));
//    }

    /**
     * 生成乘车二维码内容
     *
     * @param userData 用户签名源数据(十六进制)
     * @param QRType   二维码类型
     * @return 生成乘车二维码内容
     */
    public static String generateQR(String userData, String QRType) {
        int ll = HexUtils.hexStringToBytes(userData).length;
        int ll2 = HexUtils.hexStringToBytes(QRType).length;
        if (ll != 50 || ll2 != 1) {
            throw new QRSDKException("103", "the length of param's byte is error");
        }
        //用户密钥的模系数 签名加了00  //加了00后变为正数
//        String N1 = "00A8DA1916CB48FE8D1C0042A2209186F7AF3DF951A8E99D1595CC075125165825670EAB5113C559616E2ADFC1F53214516E02BABA786B5F57E7777C84AEF9AD7B8615B74C6D81FDBE5C0B4EED713365F866D86ECB2EDE03E532E2399484939909";
        //用户公钥指定系数
//        String E1 = "00010001";
        //用户私钥指定系数
//        String D1 = "029A06AF8559C0F352BD15C9BFF8F76489AE9450D13FEA927E87568DB0BB0F080CD615916C9DAFDE7FE72E4C03A4F3849498BFD61EB2CCE51EC780762B3E239BEF5B8F34B29944484A248E7894E5A86DE4850A121CA0332EAEE3599AFF414711";
        //本地的用户密钥
        String N1 = getLocalPrivateKeyN();//模数M
//        String N2 = getLocalPrivateKeyN();//模数M
//        int l1 = HexUtils.hexStringToBytes(N1).length;
//        int l2 = HexUtils.hexStringToBytes(N2).length;
//        BigInteger bigInteger1 = new BigInteger(N1, 16);
//        BigInteger bigInteger2 = new BigInteger(N2, 16);
        String D1 = getLocalPrivateKeyD();//私钥D指数
        if (TextUtils.isEmpty(N1) || TextUtils.isEmpty(D1))
            throw new QRSDKException("101", "The publicKey cannot be null, need to call generateKey method first");
        //生成用户签名数据(需要获取用户私钥,其实是存储在本地的)
        if (192 == N1.length()) {
            N1 = "00" + N1;
        }
        if (192 == D1.length()) {
            D1 = "00" + D1;
        }
        RSAPrivateKey rsaPrivateKey = RSAUtils.getRSAPrivateKey(N1, D1);
        RSAPublicKey rsaPublicKey = RSAUtils.getRSAPublicKey(N1, "00010001");
        //先要从数据库读取用户签名对象
        SignatureBean signatureBean = getSignatrueSyn();

        if (signatureBean == null)
            throw new QRSDKException("102", "UserCert cannot be null, need to call writeUserCert method first ");//签名不存在的情况
        //发码方签名数据(用来和用户签名元数据50字节, 一起计算HASH)
        String signatureFinal = signatureBean.getSignatureFianlEncoded();
        int finalSignatureLength = HexUtils.hexStringToBytes(signatureFinal).length;
        if (155 != finalSignatureLength)
            throw new QRSDKException("104", "查询的发码方签名数据长度有误,正确长度为155字节");//签名不存在的情况

        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("SHA1");
            byte[] decode = HexUtils.hexStringToBytes(signatureFinal + userData);
            byte[] result = digest != null ? digest.digest(decode) : new byte[0];
            //发码方签名数据+用户源数据的HASH值
            String hash1 = HexUtils.bytesToHexString(result);
            String hash1Upper = hash1 != null ? hash1.toUpperCase() : null;
            //用户源数据+Hash值
            String beforPadding = userData + hash1Upper;
            //获得文档中的ISO 9796 padding bytes填充数据
            String padded = getPaddingString(96);//用户签名数据的长度为90
            //填充完毕的数据(加密前的用户签名数据)
            String pddingFinishUserData = "4B" + padded + beforPadding + "BC";
            //使用本地保存的用户私钥,进行加密
            byte[] bytes = RSAUtils.encryptByPrivateKeyForSpilt02
                    (HexUtils.hexStringToBytes(pddingFinishUserData), rsaPrivateKey);
            //最终用户签名数据(密文)
            String userSignFinal = HexUtils.bytesToHexString(bytes);
            //用公钥解密(测试)
            byte[] bytes1 = RSAUtils.decryptByPublicKey(HexUtils.hexStringToBytes(userSignFinal), rsaPublicKey);
            String pddingFinishUserDataTest = HexUtils.bytesToHexString(bytes1);
            //组装二维码内容中的发码方最终签名+用户最终签名
            String tem = signatureFinal + userSignFinal;
            //字节长度
            int lp = HexUtils.hexStringToBytes(tem).length;
            //字节长度转为16进制串
            String lengthStr = Integer.toHexString(lp);
            //将16进制串转为四个长度的16进制串(不足的在高位补0)
            StringBuilder sb = new StringBuilder(lengthStr);
            for (int i = 0; i < 4 - lengthStr.length(); i++) {
                sb.insert(0, "0");
            }
            //获得乘车码后续长度的十六进制串(4个字节)
            String lenHex = sb.toString();
//            String QR = "01010101" + lenHex + tem;
            String QRVersion = signatureBean.getQRVersion();//二维码版本
            String keyIndex = signatureBean.getKeyIndex();//秘钥索引
            String keyVersion = signatureBean.getKeyVersion();//密钥版本
            //二维码版本+二维码类型+秘钥索引+密钥版本+后续长度+(发码方最终签名+用户最终签名)
            String QR = QRVersion + QRType + keyIndex
                    + keyVersion + lenHex + tem;
            return QR.toUpperCase();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    public static void generateQR(String userData, String QRType, QRCallBack callBack) {
        int ll = HexUtils.hexStringToBytes(userData).length;
        int ll2 = HexUtils.hexStringToBytes(QRType).length;
        if (ll != 50) {
            callBack.onResult("", 101);//用户签名数据源数据参数长度有误,正确长度为50字节
            return;
        }
        if (ll2 != 1) {
            callBack.onResult("", 102);//QRType参数长度有误,正确长度为1字节
            return;
        }
        //用户密钥的模系数 签名加了00  //加了00后变为正数
        //本地的用户密钥
        String N1 = getLocalPrivateKeyN();//模数M
//        String N2 = getLocalPrivateKeyN();//模数M
//        int l1 = HexUtils.hexStringToBytes(N1).length;
//        int l2 = HexUtils.hexStringToBytes(N2).length;
//        BigInteger bigInteger1 = new BigInteger(N1, 16);
//        BigInteger bigInteger2 = new BigInteger(N2, 16);
        String D1 = getLocalPrivateKeyD();//私钥D指数
        if (TextUtils.isEmpty(N1)) {
            callBack.onResult("", 103);//获得的本地私钥模数N为空
            return;
        }
        if (TextUtils.isEmpty(D1)) {
            callBack.onResult("", 104);//获得的本地私钥指数D为空
            return;
        }
        //生成用户签名数据(需要获取用户私钥,其实是存储在本地的)
        if (192 == N1.length()) {
            N1 = "00" + N1;
        }
        if (192 == D1.length()) {
            D1 = "00" + D1;
        }
        //获得用户的公钥与私钥
        RSAPrivateKey rsaPrivateKey = RSAUtils.getRSAPrivateKey(N1, D1);
        byte[] encoded = rsaPrivateKey.getEncoded();
        RSAPublicKey rsaPublicKey = RSAUtils.getRSAPublicKey(N1, "00010001");
        //先要从数据库读取用户签名对象
        SignatureBean signatureBean = getSignatrueSyn();

        if (signatureBean == null) {
            callBack.onResult("", 105);//从数据库读取用户签名对象为空
            return;
        }

        //发码方签名数据(用来和用户签名元数据50字节, 一起计算HASH)
        String signatureFinal = signatureBean.getSignatureFianlEncoded();
        int finalSignatureLength = HexUtils.hexStringToBytes(signatureFinal).length;
        if (155 != finalSignatureLength) {
            callBack.onResult("", 106);//从sdk数据库获得的发码方签名数据长度有误,正确长度为155字节
            return;
        }

        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("SHA1");
            byte[] decode = HexUtils.hexStringToBytes(signatureFinal + userData);
            byte[] result = digest != null ? digest.digest(decode) : new byte[0];
            //发码方签名数据+用户源数据的HASH值
            String hash1 = HexUtils.bytesToHexString(result);
            String hash1Upper = hash1 != null ? hash1.toUpperCase() : null;
            //用户源数据+Hash值
            String beforPadding = userData + hash1Upper;
            //获得文档中的ISO 9796 padding bytes填充数据
            String padded = getPaddingString(96);//用户签名数据的长度为90
            //填充完毕的数据(加密前的用户签名数据)
            String pddingFinishUserData = "4B" + padded + beforPadding + "BC";
            byte[] userSignFinalPlainBytes = HexUtils.hexStringToBytes(pddingFinishUserData);
            if (96 != userSignFinalPlainBytes.length) {
                callBack.onResult("", 107);//加密前,填充的字节有误.填充后的字节长度应为96
                return;
            }
            //使用本地保存的用户私钥,进行加密
            byte[] bytes = RSAUtils.encryptByPrivateKeyForSpilt02
                    (HexUtils.hexStringToBytes(pddingFinishUserData), rsaPrivateKey);
            //最终用户签名数据(密文)
            String userSignFinal = HexUtils.bytesToHexString(bytes);

            //用公钥解密(测试)
//            byte[] bytes1 = RSAUtils.decryptByPublicKey(HexUtils.hexStringToBytes(userSignFinal), rsaPublicKey);
//            String pddingFinishUserDataTest = HexUtils.bytesToHexString(bytes1);
            //组装二维码内容中的发码方最终签名+用户最终签名
            String tem = signatureFinal + userSignFinal;
            //字节长度
            int lp = HexUtils.hexStringToBytes(tem).length;
            if (251 != lp) {
                callBack.onResult("", 108);//组装二维码内容中的发码方最终签名+用户最终签名,长度有误,正确长度为251字节
                return;
            }
            //字节长度转为16进制串
            String lengthStr = Integer.toHexString(lp);
            //将16进制串转为四个长度的16进制串(不足的在高位补0)
            StringBuilder sb = new StringBuilder(lengthStr);
            for (int i = 0; i < 4 - lengthStr.length(); i++) {
                sb.insert(0, "0");
            }
            //获得乘车码后续长度的十六进制串(4个字符)
            String lenHex = sb.toString();
            int lengthByteSize = HexUtils.hexStringToBytes(lenHex).length;
            if (lengthByteSize != 2) {
                callBack.onResult("", 109);//发码方最终签名+用户最终签名的长度的int值的字节长度为2
                return;
            }
            String QRVersion = signatureBean.getQRVersion();//二维码版本
            String keyIndex = signatureBean.getKeyIndex();//秘钥索引
            String keyVersion = signatureBean.getKeyVersion();//密钥版本
            //二维码版本+二维码类型+秘钥索引+密钥版本+后续长度+(发码方最终签名+用户最终签名)
            String QR = QRVersion + QRType + keyIndex
                    + keyVersion + lenHex + tem;
            callBack.onResult(QR, -1);//二维码数据生成正确,长度是257字节
        } catch (Exception e) {
            e.printStackTrace();
            callBack.onResult("", 110);//用户私钥加密或者Hash计算出错
          }
    }

    @NonNull
    private static String getPaddingString(int lenght) {
        int j = lenght - 72;
        StringBuilder buffer = new StringBuilder();
        for (int i = 0; i < j; i++) {
            buffer.append("BB");
        }
        return buffer.toString();
    }

    /**
     * 获得本地用户证书(同步)
     *
     * @return 签名证书
     */
    private static SignatureBean getSignatrueSyn() {
        List<SignatureBean> all = DataSupport.findAll(SignatureBean.class);
        if (all != null && all.size() > 0) {
            return all.get(0);
        }
        return null;
    }

    /**
     * 将密钥对保存至本地
     * 保存的是base64编码后的密钥
     */
    private static void saveKeyToLocal(final RSAPublicKey publicKey,
                                       final RSAPrivateKey privateKey, final GenerateKeyCallBack callBack) {
        new Thread(new Runnable() {
            @Override
            public void run() {

                DataSupport.deleteAll(KeyBean.class);//保存之前先清空
                // 由密钥对象转化为密钥字符串(保存到本地的是BASE64字符串)
//                String publicKeyString = Base64Decoder01.encode(publicKey.getEncoded());
                // 得到私钥字符串(保存到本地的是BASE64字符串)
//                String privateKeyString = Base64Decoder01.encode(privateKey.getEncoded());
                KeyBean keyBean = new KeyBean();
                keyBean.setPk("01");
//                keyBean.setPublicKeyStr(publicKeyString);
//                keyBean.setPrivateKeyStr(privateKeyString);
                BigInteger modulus1 = publicKey.getModulus();
                byte[] Nbytes1 = modulus1.toByteArray();
                String N = HexUtils.bytesToHexString(Nbytes1);
                int length = N.length();
                if (length == 194) {
                    N = N.substring(2);
                }
                BigInteger privateExponent = privateKey.getPrivateExponent();
                byte[] Dbytes2 = privateExponent.toByteArray();
                String D = HexUtils.bytesToHexString(Dbytes2);
                if (194 == D.length()) {
                    D = D.substring(2);
                }
                keyBean.setKeyN(N);
                keyBean.setKeyD(D);
                boolean success = keyBean.save();
                callBack.onSaveResult(success, N);//返回十六进制的公钥
                //todo 测试使用
//                DButil01.copyDataBaseToSD(SDKApplication.getContext(), "key", "sdDemo02");

            }
        }).start();
    }

    private static void saveKeyToLocal(final RSAPublicKey publicKey,
                                       final RSAPrivateKey privateKey) {
        new Thread(new Runnable() {
            @Override
            public void run() {

                DataSupport.deleteAll(KeyBean.class);//保存之前先清空
                // 由密钥对象转化为密钥字符串(保存到本地的是BASE64字符串)
//                String publicKeyString = Base64Decoder01.encode(publicKey.getEncoded());
                // 得到私钥字符串(保存到本地的是BASE64字符串)
//                String privateKeyString = Base64Decoder01.encode(privateKey.getEncoded());
                KeyBean keyBean = new KeyBean();
                keyBean.setPk("01");
//                keyBean.setPublicKeyStr(publicKeyString);
//                keyBean.setPrivateKeyStr(privateKeyString);
                BigInteger modulus1 = publicKey.getModulus();
                byte[] Nbytes1 = modulus1.toByteArray();
                String N = HexUtils.bytesToHexString(Nbytes1);
                int length = N.length();
                if (length == 194) {
                    N = N.substring(2);
                }
                BigInteger privateExponent = privateKey.getPrivateExponent();
                byte[] Dbytes2 = privateExponent.toByteArray();
                String D = HexUtils.bytesToHexString(Dbytes2);
                if (194 == D.length()) {
                    D = D.substring(2);
                }
                keyBean.setKeyN(N);
                keyBean.setKeyD(D);
                boolean success = keyBean.save();
//                callBack.onSaveResult(success, N);//返回十六进制的公钥
                //todo 测试使用
//                DButil01.copyDataBaseToSD(SDKApplication.getContext(), "key", "sdDemo02");

            }
        }).start();
    }

    private static SignatureBean updateSignatureOld(String certData) {
//        String tt = "abcd125";
//        byte[] bytes4 = HexUtils.hexStringToBytes(tt);
//        byte[] bytes5 = subBytes(bytes4, 1, 1);
//        String s1 = HexUtils.bytesToHexString(bytes5);
        UserCert userCert = GsonHelper.convertEntity(certData, UserCert.class); //用户传进来的所以数据源
        if (null == userCert) {
            throw new QRSDKException("201", "用户app传入的certData,转为UserCert实体失败");
        }


        SignatureBean signatureBean = new SignatureBean();
        signatureBean.setPk("01");
        int keyVersion = userCert.getKeyVersion();
        int qrVersion = userCert.getQRVersion();

        String keyVersionHex = String.format("%1$02X", keyVersion);
        String qrVersionHex = String.format("%1$02X", qrVersion);
        if (HexUtils.hexStringToBytes(keyVersionHex).length != 1) {
            throw new QRSDKException("202", "keyVersion的字节长度有误,正确长度为1个字节");
        }
        if (HexUtils.hexStringToBytes(qrVersionHex).length != 1) {
            throw new QRSDKException("203", "qrVersion的字节长度有误,正确长度为1个字节");
        }
        signatureBean.setKeyVersion(keyVersionHex);
        signatureBean.setQRVersion(qrVersionHex);
        String keyCer = userCert.getKeyCer(); //下方的证书(发码方证书结构)//265长度
        byte[] bytes3 = HexUtils.hexStringToBytes(keyCer);
        if (bytes3.length != 265) {
            throw new QRSDKException("204", "发码方证书keyCer的长度有误,正确长度为265个字节");
        }
        signatureBean.setKeyCer(keyCer);
        RSAPublicKey rsaPublicKey = null;
        byte[] bytesPublicKeyTemp = subBytes(bytes3, 9, 128);//获得发码方的公钥模数N (用来解密密文signatur1)
        String N = HexUtils.bytesToHexString(bytesPublicKeyTemp);
        byte[] bytesPublicKey = HexUtils.hexStringToBytes("00" + N);//加00使字节数组变为正大数
        rsaPublicKey = RSAUtils.generateRSAPublicKey(bytesPublicKey,//keyCer中的公钥(验证是否被篡改)
                HexUtils.hexStringToBytes("00010001"));
        //验证是否被篡改
        boolean signed = verifySign(bytes3, rsaPublicKey);
        if (!signed) {
            throw new QRSDKException("206", "发码方证书keyCer验签未通过");
        }
        String keyIndex = HexUtils.bytesToHexString(subBytes(bytes3, 8, 1));//密钥索引
        signatureBean.setKeyIndex(keyIndex);
        String cer = userCert.getCer();// 发码方数据签名signatureFinal//用户证书密文(16进制)155长度
        byte[] bytes = HexUtils.hexStringToBytes(cer);
        if (bytes.length != 155) {
            throw new QRSDKException("205", "发码方数据签名长度有误,正确长度为155字节");
        }
        signatureBean.setSignatureFianlEncoded(cer);
        byte[] bytes1 = subBytes(bytes, 0, 128);
        String signatur1 = HexUtils.bytesToHexString(bytes1); // 密文signatur1
        try {
            //使用公钥解密(signatur1)
            byte[] bytes2 = RSAUtils.decryptByPublicKeyForSpilt
                    (bytes1, rsaPublicKey);//密文是128个字节, 解密时不需要填充
            String signature1_plain = HexUtils.bytesToHexString(bytes2);//获得signatur1的明文
            //保存明文, 解析明文,保存需要的数据,如有效期
            if (bytes2.length == 128) {
                signatureBean.setSignature1Plain(signature1_plain);
                byte[] bytesValidTime = subBytes(bytes2, 29, 4);
                String validTimeStr = HexUtils.bytesToHexString(bytesValidTime);
                //变换为十进制, 截止有效时间戳
                Long validTime = Long.parseLong(validTimeStr, 16);
                //int validTime = 24 * 17 * 60 * 60 * 1000;//毫秒(假设有效时长为24小时,到月底)
                //发码签名证书的截止有效时间戳
                signatureBean.setValidTime(validTime);
                return signatureBean;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            throw new QRSDKException("207", "使用公钥解密密文signatur1失败,密文长度为" + HexUtils.bytesToHexString(bytes1));
        }
    }

    //将错误信息返回
    private static SignatureBean updateSignature(String certData, WriteUsertCertCallBack certCallBack) {
//        String tt = "abcd125";
//        byte[] bytes4 = HexUtils.hexStringToBytes(tt);
//        byte[] bytes5 = subBytes(bytes4, 1, 1);
//        String s1 = HexUtils.bytesToHexString(bytes5);
        UserCert userCert = GsonHelper.convertEntity(certData, UserCert.class); //用户传进来的所以数据源
        if (null == userCert) {
            certCallBack.onResult(false, 201);
            return null;
//            throw new QRSDKException("201", "用户app传入的certData,转为UserCert实体失败");
        }


        SignatureBean signatureBean = new SignatureBean();
        signatureBean.setPk("01");
        int keyVersion = userCert.getKeyVersion();
        int qrVersion = userCert.getQRVersion();

        String keyVersionHex = String.format("%1$02X", keyVersion);
        String qrVersionHex = String.format("%1$02X", qrVersion);
        if (HexUtils.hexStringToBytes(keyVersionHex).length != 1) {
            certCallBack.onResult(false, 202);
            return null;
//            throw new QRSDKException("202", "keyVersion的字节长度有误,正确长度为1个字节");
        }
        if (HexUtils.hexStringToBytes(qrVersionHex).length != 1) {
            certCallBack.onResult(false, 203);
            return null;
//            throw new QRSDKException("203", "qrVersion的字节长度有误,正确长度为1个字节");
        }
        signatureBean.setKeyVersion(keyVersionHex);
        signatureBean.setQRVersion(qrVersionHex);
        String keyCer = userCert.getKeyCer(); //下方的证书(发码方证书结构)//265长度
        byte[] bytes3 = HexUtils.hexStringToBytes(keyCer);
        if (bytes3.length != 265) {
            certCallBack.onResult(false, 204);
            return null;
//            throw new QRSDKException("204", "发码方证书keyCer的长度有误,正确长度为265个字节");
        }
        signatureBean.setKeyCer(keyCer);
        RSAPublicKey rsaPublicKey = null;
        byte[] bytesPublicKeyTemp = subBytes(bytes3, 9, 128);//获得发码方的公钥模数N (用来解密密文signatur1)
        String N = HexUtils.bytesToHexString(bytesPublicKeyTemp);
        byte[] bytesPublicKey = HexUtils.hexStringToBytes("00" + N);//加00使字节数组变为正大数
        rsaPublicKey = RSAUtils.generateRSAPublicKey(bytesPublicKey,//keyCer中的公钥(验证是否被篡改)
                HexUtils.hexStringToBytes("00010001"));
        //验证是否被篡改
        boolean signed = verifySign(bytes3, rsaPublicKey);
        if (!signed) {
//            throw new QRSDKException("206", "发码方证书keyCer验签未通过");
            certCallBack.onResult(false, 206);
            return null;
        }
        String keyIndex = HexUtils.bytesToHexString(subBytes(bytes3, 8, 1));//密钥索引
        signatureBean.setKeyIndex(keyIndex);
        String cer = userCert.getCer();// 发码方数据签名signatureFinal//用户证书密文(16进制)155长度
        byte[] bytes = HexUtils.hexStringToBytes(cer);
        if (bytes.length != 155) {
            certCallBack.onResult(false, 205);
            return null;
//            throw new QRSDKException("205", "发码方数据签名长度有误,正确长度为155字节");
        }
        signatureBean.setSignatureFianlEncoded(cer);
        byte[] bytes1 = subBytes(bytes, 0, 128);
        String signatur1 = HexUtils.bytesToHexString(bytes1); // 密文signatur1
        try {
            //使用公钥解密(signatur1)
            byte[] bytes2 = RSAUtils.decryptByPublicKeyForSpilt
                    (bytes1, rsaPublicKey);//密文是128个字节, 解密时不需要填充
            String signature1_plain = HexUtils.bytesToHexString(bytes2);//获得signatur1的明文
            //保存明文, 解析明文,保存需要的数据,如有效期
            if (bytes2.length == 128) {
                signatureBean.setSignature1Plain(signature1_plain);
                byte[] bytesValidTime = subBytes(bytes2, 29, 4);
                String validTimeStr = HexUtils.bytesToHexString(bytesValidTime);
                //变换为十进制, 截止有效时间戳
                Long validTime = Long.parseLong(validTimeStr, 16);
//                long time = new Date().getTime()/1000;
                //int validTime = 24 * 17 * 60 * 60 * 1000;//毫秒(假设有效时长为24小时,到月底)
                //发码签名证书的截止有效时间戳
                signatureBean.setValidTime(validTime);
                return signatureBean;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            certCallBack.onResult(false, 207);
            return null;
        }
    }

    private static SignatureBean updateSignature(String certData) {
        UserCert userCert = GsonHelper.convertEntity(certData, UserCert.class); //用户传进来的所以数据源
        if (null == userCert) {
            return null;
        }
        SignatureBean signatureBean = new SignatureBean();
        signatureBean.setPk("01");
        int keyVersion = userCert.getKeyVersion();
        int qrVersion = userCert.getQRVersion();

        String keyVersionHex = String.format("%1$02X", keyVersion);
        String qrVersionHex = String.format("%1$02X", qrVersion);
        if (HexUtils.hexStringToBytes(keyVersionHex).length != 1) {
            return null;
        }
        if (HexUtils.hexStringToBytes(qrVersionHex).length != 1) {
            return null;
        }
        signatureBean.setKeyVersion(keyVersionHex);
        signatureBean.setQRVersion(qrVersionHex);
        String keyCer = userCert.getKeyCer(); //下方的证书(发码方证书结构)//265长度
        byte[] bytes3 = HexUtils.hexStringToBytes(keyCer);
        if (bytes3.length != 265) {
            return null;
        }
        signatureBean.setKeyCer(keyCer);
        RSAPublicKey rsaPublicKey = null;
        byte[] bytesPublicKeyTemp = subBytes(bytes3, 9, 128);//获得发码方的公钥模数N (用来解密密文signatur1)
        String N = HexUtils.bytesToHexString(bytesPublicKeyTemp);
        byte[] bytesPublicKey = HexUtils.hexStringToBytes("00" + N);//加00使字节数组变为正大数
        rsaPublicKey = RSAUtils.generateRSAPublicKey(bytesPublicKey,//keyCer中的公钥(验证是否被篡改)
                HexUtils.hexStringToBytes("00010001"));
        //验证是否被篡改
        boolean signed = verifySign(bytes3, rsaPublicKey);
        if (!signed) {
            return null;
        }
        String keyIndex = HexUtils.bytesToHexString(subBytes(bytes3, 8, 1));//密钥索引
        signatureBean.setKeyIndex(keyIndex);
        String cer = userCert.getCer();// 发码方数据签名signatureFinal//用户证书密文(16进制)155长度
        byte[] bytes = HexUtils.hexStringToBytes(cer);
        if (bytes.length != 155) {
            return null;
        }
        signatureBean.setSignatureFianlEncoded(cer);
        byte[] bytes1 = subBytes(bytes, 0, 128);
        String signatur1 = HexUtils.bytesToHexString(bytes1); // 密文signatur1
        try {
            //使用公钥解密(signatur1)
            byte[] bytes2 = RSAUtils.decryptByPublicKeyForSpilt
                    (bytes1, rsaPublicKey);//密文是128个字节, 解密时不需要填充
            String signature1_plain = HexUtils.bytesToHexString(bytes2);//获得signatur1的明文
            //保存明文, 解析明文,保存需要的数据,如有效期
            if (bytes2.length == 128) {
                signatureBean.setSignature1Plain(signature1_plain);
                byte[] bytesValidTime = subBytes(bytes2, 29, 4);
                String validTimeStr = HexUtils.bytesToHexString(bytesValidTime);
                //变换为十进制, 截止有效时间戳
                Long validTime = Long.parseLong(validTimeStr, 16);
//                long time = new Date().getTime()/1000;
                //int validTime = 24 * 17 * 60 * 60 * 1000;//毫秒(假设有效时长为24小时,到月底)
                //发码签名证书的截止有效时间戳
                signatureBean.setValidTime(validTime);
                return signatureBean;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static boolean verifySign(byte[] bytes3, RSAPublicKey rsaPublicKey) {
        byte[] bytes4 = subBytes(bytes3, 0, 137);//被签名的数据(明文)
//        String palin = HexUtils.bytesToHexString(bytes4);
        byte[] bytes5 = subBytes(bytes3, 137, 128);//签名
        try {
            byte[] bytesDe = RSAUtils.decryptByPublicKey(bytes5, rsaPublicKey);
            byte[] bytes = subBytes(bytesDe, bytesDe.length - 20, 20);
//            String Hash = HexUtils.bytesToHexString(bytes);
            MessageDigest digest = MessageDigest.getInstance("SHA1");
            byte[] digest1 = digest.digest(bytes4);
//            String hash01 = HexUtils.bytesToHexString(digest1);
            boolean equals = Arrays.equals(bytes, digest1);
            return equals;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获得本地保存的密钥系数N
     *
     * @return 私钥字符串
     */
    private static String getLocalPrivateKeyN() {
        List<KeyBean> all = DataSupport.findAll(KeyBean.class);
        if (all != null && all.size() > 0) {
            return all.get(0).getKeyN();
        }
        return "";
    }

    /**
     * 获得本地保存的私钥系数D
     *
     * @return 私钥字符串
     */
    private static String getLocalPrivateKeyD() {
        List<KeyBean> all = DataSupport.findAll(KeyBean.class);
        if (all != null && all.size() > 0) {
            return all.get(0).getKeyD();
        }
        return "";
    }

    /**
     * 获得本地保存的私钥
     *
     * @return 私钥字符串
     */
    private static String getLocalPrivateKey() {
        List<KeyBean> all = DataSupport.findAll(KeyBean.class);
        if (all != null && all.size() > 0) {
            return all.get(0).getPrivateKeyStr();
        }
        return "";
    }

    /**
     * 获得本地保存的公钥
     *
     * @return 公钥字符串
     */
    private String getLocalPublicKey() {
        List<KeyBean> all = DataSupport.findAll(KeyBean.class);
        if (all != null && all.size() > 0) {
            return all.get(0).getPublicKeyStr();
        }
        return "";
    }

    /**
     * 获得用户签名的剩余有效时间
     *
     * @return 截止时间戳
     */
    private static long getRemainValidTime(SignatureBean signatureBean) {
        //截止时间戳
        long validTime1 = signatureBean.getValidTime();
        //现在时间
//        long now = new Date().getTime();
        //剩余有效时间
//        long left_time = validTime1 - now;
        return validTime1;//截止时间戳
    }

    public interface WriteUsertCertCallBack {

        void onResult(boolean success, int errorCode);
    }

    public interface GenerateKeyCallBack {
        void onSaveResult(boolean success, String key);
    }

    public interface FindUsertCertCallBack {
        void onSuccess(long validTime);

        void onFail(int f);
    }

    public interface QRCallBack {
        void onResult(String success, int errorCode);
    }

    public static byte[] subBytes(byte[] src, int begin, int count) {
        byte[] bs = new byte[count];
        System.arraycopy(src, begin, bs, 0, count);
        return bs;
    }
}
